#ifndef UHM_UTIL_ID_HXX
#define UHM_UTIL_ID_HXX

#define UHM_UTIL_ID_UNROLL 2

namespace uhm {

  template<class T_, Int_ N> class ID_ : public Disp_ {
  private:
  protected:
    // _id[0] is most important, the others are aux information.
    T_ _id[N];

    virtual void assign(const ID_ &b) { 
#pragma unroll(UHM_UTIL_ID_UNROLL)
      for (int i=0;i<N;++i) 
        _id[i] = b._id[i];
    }

  public:
    void set_id(Int_ i, T_ val) { _id[i] = val; }
    T_ get_id(Int_ i) const { return _id[i]; }
    T_& id(Int_ i) { return _id[i]; }

    virtual std::ostream& content(std::ostream& os) const {
      os << "Id:(";
      for (Int_ i=0;i<N;++i)
        os << this->get_id(i) << " ";
      os << ")";
      return os;
    }

    virtual Bool_ less(const ID_ &b) const {
#pragma unroll(UHM_UTIL_ID_UNROLL)
      for (Int_ i=0;i<N;++i) {
        if (this->get_id(i) < b.get_id(i)) ;
        else 
          return false;
      }
      return true;
    }

    virtual Bool_ is_equal(const ID_ &b) const {
#pragma unroll(UHM_UTIL_ID_UNROLL)
      for (Int_ i=0;i<N;++i)
        if (this->get_id(i) == b.get_id(i)) ;
        else
          return false;
      return true;
    }
    
    virtual ID_& equate(const ID_ &b) {
#pragma unroll(UHM_UTIL_ID_UNROLL)
      for (Int_ i=0;i<N;++i)
        this->_id[i] = b._id[i];
      return (*this);
    }

    virtual ID_& pp() {
      ++this->_id[0];
      return (*this);
    }

    virtual ID_& mm() {
      --this->_id[0];
      return (*this);
    }

    virtual Bool_ operator<(const ID_ &b) const  { return this->less(b);    }
    virtual Bool_ operator==(const ID_ &b) const { return this->is_equal(b);}
    virtual Bool_ operator!=(const ID_ &b) const { return !(*this == b);    }

    virtual ID_& operator=(const ID_ &b)         { return this->equate(b);  }

    virtual ID_& operator++()                    { return this->pp();       }
    virtual ID_& operator--()                    { return this->mm();       }
  };
}


#endif
